package com.benjaminwan.read.free.ui.mouse

import android.app.Service
import android.os.Bundle
import android.os.VibrationEffect
import android.os.Vibrator
import android.view.GestureDetector
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.SeekBar
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState
import com.benjaminwan.read.free.R
import com.benjaminwan.read.free.base.fragment.BaseFragment
import com.benjaminwan.read.free.base.viewmodel.state
import com.benjaminwan.read.free.databinding.FragmentMouseBinding
import com.benjaminwan.read.free.model.enums.Horizontal
import com.benjaminwan.read.free.model.enums.MouseButton
import com.benjaminwan.read.free.model.enums.Vertical
import com.benjaminwan.read.free.ui.main.MainViewModel
import com.benjaminwan.read.free.ui.settings.SettingsViewModel
import com.orhanobut.logger.Logger

class MouseFragment : BaseFragment(), View.OnClickListener, SeekBar.OnSeekBarChangeListener,
    View.OnTouchListener {

    private val mainVM by activityViewModel(MainViewModel::class)
    private val settingsVM by activityViewModel(SettingsViewModel::class)

    private val vibrator: Vibrator by lazy {
        requireContext().getSystemService(Service.VIBRATOR_SERVICE) as Vibrator
    }

    private val vibratorEnable: Boolean by lazy {
        settingsVM.state.vibratorEnable
    }

    private val vibrationEffect = VibrationEffect.createOneShot(
        100, VibrationEffect.DEFAULT_AMPLITUDE
    )

    private var prevMoveX: Int = 0
    private var prevMoveY: Int = 0
    private var prevScrollY = 0

    private val gestureDetector: GestureDetector by lazy {
        val detector =
            GestureDetector(requireContext(), object : GestureDetector.OnGestureListener {
                override fun onShowPress(p0: MotionEvent?) {
                    Logger.i("onShowPress")
                }

                override fun onSingleTapUp(p0: MotionEvent?): Boolean {
                    Logger.i("onSingleTapUp")
                    return false
                }

                override fun onDown(event: MotionEvent?): Boolean {
                    Logger.i("onDown:$event")
                    return true
                }

                override fun onFling(
                    p0: MotionEvent?, p1: MotionEvent?,
                    p2: Float, p3: Float
                ): Boolean {
                    Logger.i("onFling")
                    return false
                }

                override fun onScroll(
                    event1: MotionEvent?, event2: MotionEvent?,
                    x: Float, y: Float
                ): Boolean {
                    Logger.i("onScroll:event1=$event1, event2=$event2, x=$x, y=$y")
                    event1 ?: return false
                    event2 ?: return false
                    if (event2.pointerCount > 1) {
                        val scrollSpeed = mainVM.state.scrollSpeed
                        mainVM.mouseScroll((y * scrollSpeed * 0.1).toInt())
                    } else {
                        val moveSpeed = mainVM.state.moveSpeed
                        mainVM.mouseMove(-(x * moveSpeed).toInt(), -(y * moveSpeed).toInt())
                    }
                    return false
                }

                override fun onLongPress(p0: MotionEvent?) {
                    Logger.i("onLongPress")
                    mainVM.mouseButtonClick(MouseButton.Right.ordinal)
                }
            })
        detector.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener {
            override fun onDoubleTap(event: MotionEvent?): Boolean {
                Logger.i("onDoubleTap:$event")
                event ?: return false
                mainVM.mouseButtonDoubleClick(MouseButton.Left.ordinal)
                return false
            }

            override fun onDoubleTapEvent(event: MotionEvent?): Boolean {
                //Logger.i("onDoubleTapEvent")
                return false
            }

            override fun onSingleTapConfirmed(event: MotionEvent?): Boolean {
                Logger.i("onSingleTapConfirmed:$event")
                mainVM.mouseButtonClick(MouseButton.Left.ordinal)
                return false
            }
        })
        detector
    }
    private lateinit var binding: FragmentMouseBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentMouseBinding.inflate(layoutInflater)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setHasOptionsMenu(true)
        initViews()
        if (vibratorEnable)
            vibrator.vibrate(vibrationEffect)
    }

    private fun initViews() {
        binding.mouseView.setOnTouchListener(this)
        binding.scrollView.setOnTouchListener(this)
        binding.moveSpeedBar.setOnSeekBarChangeListener(this)
        binding.scrollSpeedBar.setOnSeekBarChangeListener(this)
        binding.leftBtn.setOnTouchListener(this)
        binding.middleBtn.setOnTouchListener(this)
        binding.rightBtn.setOnTouchListener(this)
        binding.left10StepBtn.setOnClickListener(this)
        binding.right10StepBtn.setOnClickListener(this)
        binding.up10StepBtn.setOnClickListener(this)
        binding.down10StepBtn.setOnClickListener(this)
        binding.left100StepBtn.setOnClickListener(this)
        binding.right100StepBtn.setOnClickListener(this)
        binding.up100StepBtn.setOnClickListener(this)
        binding.down100StepBtn.setOnClickListener(this)
        binding.dragLeftBtn.setOnClickListener(this)
        binding.dragRightBtn.setOnClickListener(this)
        binding.dragUpBtn.setOnClickListener(this)
        binding.dragDownBtn.setOnClickListener(this)
    }

    override fun onClick(view: View?) {
        view ?: return
        when (view.id) {
            R.id.left10StepBtn -> {
                mainVM.mouseMove(-10, 0)
            }

            R.id.right10StepBtn -> {
                mainVM.mouseMove(10, 0)
            }

            R.id.up10StepBtn -> {
                mainVM.mouseMove(0, -10)
            }

            R.id.down10StepBtn -> {
                mainVM.mouseMove(0, 10)
            }

            R.id.left100StepBtn -> {
                mainVM.mouseMove(-100, 0)
            }

            R.id.right100StepBtn -> {
                mainVM.mouseMove(100, 0)
            }

            R.id.up100StepBtn -> {
                mainVM.mouseMove(0, -100)
            }

            R.id.down100StepBtn -> {
                mainVM.mouseMove(0, 100)
            }

            R.id.dragLeftBtn -> {
                mainVM.doMouseDrag(
                    Horizontal.LEFT, Vertical.UP,
                    (150..150), (0..0), (5..7), (1..1)
                )
            }

            R.id.dragRightBtn -> {
                mainVM.doMouseDrag(
                    Horizontal.RIGHT, Vertical.DOWN,
                    (150..150), (0..0), (5..7), (1..1)
                )
            }

            R.id.dragUpBtn -> {
                mainVM.doMouseDrag(
                    Horizontal.LEFT, Vertical.UP,
                    (0..0), (200..200), (1..1), (5..7)
                )
            }

            R.id.dragDownBtn -> {
                mainVM.doMouseDrag(
                    Horizontal.RIGHT, Vertical.DOWN,
                    (0..0), (200..200), (1..1), (5..7)
                )
            }

            else -> {
            }
        }
        if (vibratorEnable)
            vibrator.vibrate(vibrationEffect)
    }

    override fun onTouch(view: View?, event: MotionEvent?): Boolean {
        view ?: return false
        event ?: return false
        when (view.id) {
            R.id.leftBtn, R.id.middleBtn, R.id.rightBtn -> {
                val which = view.tag.toString().toInt()
                when (event.action) {
                    MotionEvent.ACTION_DOWN -> {
                        mainVM.mouseButtonDown(which)
                        if (vibratorEnable)
                            vibrator.vibrate(vibrationEffect)
                    }

                    MotionEvent.ACTION_UP -> mainVM.mouseButtonUp(which)
                }
                return false
            }

            R.id.mouseView -> {
                /*val moveSpeed = mainVM.state.moveSpeed
                when (motionEvent.action) {
                    MotionEvent.ACTION_DOWN -> {
                        prevMoveX = ((motionEvent.x * moveSpeed).toInt())
                        prevMoveY = ((motionEvent.y * moveSpeed).toInt())
                    }
                    MotionEvent.ACTION_MOVE -> {
                        val x = (motionEvent.x * moveSpeed).toInt()
                        val y = (motionEvent.y * moveSpeed).toInt()
                        mainVM.mouseMove(x - prevMoveX, y - prevMoveY)
                        prevMoveX = x
                        prevMoveY = y
                    }
                }
                return true*/
                return gestureDetector.onTouchEvent(event)
            }

            R.id.scrollView -> {
                val scrollSpeed = mainVM.state.scrollSpeed
                when (event.action) {
                    MotionEvent.ACTION_DOWN -> {
                        prevScrollY = (event.y * scrollSpeed * 0.1).toInt()
                    }

                    MotionEvent.ACTION_MOVE -> {
                        val y = (event.y * scrollSpeed * 0.1).toInt()
                        mainVM.mouseScroll(prevScrollY - y)
                        prevScrollY = y
                    }
                }
                return true
            }

            else -> {
                return false
            }
        }
    }

    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        seekBar ?: return
        when (seekBar.id) {
            R.id.moveSpeedBar -> {
                if (fromUser) mainVM.setMoveSpeed(progress)
            }

            R.id.scrollSpeedBar -> {
                if (fromUser) mainVM.setScrollSpeed(progress)
            }

            else -> {
            }
        }
    }

    override fun onStartTrackingTouch(seekBar: SeekBar?) {

    }

    override fun onStopTrackingTouch(seekBar: SeekBar?) {

    }

    /*override fun onPrepareOptionsMenu(menu: Menu) {
        menu.findItem(R.id.action_disconnect).isVisible = false
        super.onPrepareOptionsMenu(menu)
    }*/

    /*fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        Logger.i("onKeyDown keyCode=$keyCode,event=$event")
        event ?: return false
        val keyboardSender = mainVM.keyboardSender ?: return false
        return keyboardSender.sendKeyboard(keyCode, event, 0)
    }

    fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        Logger.i("onKeyUp keyCode=$keyCode,event=$event")
        event ?: return false
        val keyboardSender = mainVM.keyboardSender ?: return false
        return keyboardSender.sendKeyboard(keyCode, event, 0)
    }*/

    override fun invalidate() = withState(mainVM) { main ->
        requireActivity().invalidateOptionsMenu()
        binding.moveSpeedBar.progress = main.moveSpeed
        binding.scrollSpeedBar.progress = main.scrollSpeed
        binding.moveSpeedTv.text = getString(R.string.move_speed, main.moveSpeed)
        binding.scrollSpeedTv.text = getString(R.string.scroll_speed, main.scrollSpeed)
    }

}